-- leader keyke
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '

local map = vim.api.nvim_set_keymap
-- 复用 opt 参数
local opt = { noremap = true, silent = true }

map('n', '<C-s>', ':wa<CR>', opt)

-- Alt + hjkl  窗口之间跳转
map('n', '<A-h>', '<C-w>h', opt)
map('n', '<A-j>', '<C-w>j', opt)
map('n', '<A-k>', '<C-w>k', opt)
map('n', '<A-l>', '<C-w>l', opt)

-- 上下移动选中文本
map('v', 'J', ":move '>+1<CR>gv-gv", opt)
map('v', 'K', ":move '<-2<CR>gv-gv", opt)

-- 上下滚动浏览
map('n', '<C-j>', '4j', opt)
map('n', '<C-k>', '4k', opt)
-- ctrl u / ctrl + d  只移动9行，默认移动半屏
map('n', '<C-u>', '9k', opt)
map('n', '<C-d>', '9j', opt)

-- bufferline
-- 左右Tab切换
map('n', '<C-h>', ':BufferLineCyclePrev<CR>', opt)
map('n', '<C-l>', ':BufferLineCycleNext<CR>', opt)
-- 关闭buffer
map('n', '<C-w>', ':Bdelete!<CR>', opt)

-- comment 注释快捷键
vim.keymap.set(
  'n',
  '<C-\\>',
  '<CMD>lua require("Comment.api").toggle_current_linewise()<CR>'
)
-- coc
map(
  'i',
  '<C-t>',
  'coc#_select_confirm()',
  { silent = true, expr = true, noremap = true }
)
-- coc-symbol-line 显示代码层级
--  coc-lightbulb 如果有可用代码则显示小灯泡
vim.g.coc_global_extensions = {
  'coc-json',
  'coc-toml',
  'coc-yaml',
  'coc-symbol-line',
  'coc-lightbulb',
  'coc-symbol-line',
  'coc-snippets',
  '@yaegassy/coc-nginx',
  -- 'coc-angular',
  'coc-eslint',
  'coc-sh',
  'coc-docker',
  'coc-go',
  'coc-sumneko-lua',
  'coc-lua',
  'coc-pairs',
  -- 'coc-tsserver',
  -- 'friendly-snippets',
}

-- 插件快捷键
local pluginKeys = {}

-- nvim-tree
-- alt + m 键打开关闭tree
map('n', '<A-m>', ':NvimTreeToggle<CR>', opt)
-- 列表快捷键
pluginKeys.nvimTreeList = {
  -- 打开文件或文件夹
  { key = { '<CR>', 'o', '<2-LeftMouse>' }, action = 'edit' },
  -- 分屏打开文件
  { key = 'v', action = 'vsplit' },
  { key = 'h', action = 'split' },
  -- 显示隐藏文件
  { key = 'i', action = 'toggle_custom' }, -- 对应 filters 中的 custom (node_modules)
  { key = '.', action = 'toggle_dotfiles' }, -- Hide (dotfiles)
  -- 文件操作
  { key = '<F5>', action = 'refresh' },
  { key = 'a', action = 'create' },
  { key = 'd', action = 'remove' },
  { key = 'r', action = 'rename' },
  { key = 'x', action = 'cut' },
  { key = 'c', action = 'copy' },
  { key = 'p', action = 'paste' },
  { key = 's', action = 'system_open' },
}

-- Telescope 列表中 插入模式快捷键
pluginKeys.telescopeList = {
  i = {
    -- 上下移动
    ['<C-n>'] = 'move_selection_next',
    ['<C-p>'] = 'move_selection_previous',
    ['<Down>'] = 'move_selection_next',
    ['<Up>'] = 'move_selection_previous',
    -- 历史记录
    ['<C-j>'] = 'cycle_history_next',
    ['<C-k>'] = 'cycle_history_prev',
    -- 关闭窗口
    ['<C-c>'] = 'close',
    -- 预览窗口上下滚动
    ['<C-u>'] = 'preview_scrolling_up',
    ['<C-d>'] = 'preview_scrolling_down',
  },
}

-- 代码注释插件
-- see ./lua/plugin-config/comment.lua
pluginKeys.comment = {
  -- Normal 模式快捷键
  toggler = {
    line = 'gcc', -- 行注释
    block = 'gbc', -- 块注释
  },
  -- Visual 模式
  opleader = {
    line = 'gc',
    bock = 'gb',
  },
}

-- ctrl + /
map('n', '<C-_>', 'gcc', { noremap = false })
map('v', '<C-_>', 'gcc', { noremap = false })

pluginKeys.mapDiffview = function()
  local actions = require('diffview.actions')
  return {
    disable_defaults = false, -- Disable the default keymaps
    view = {
      -- The `view` bindings are active in the diff buffers, only when the current
      -- tabpage is a Diffview.
      ['<tab>'] = actions.select_next_entry, -- Open the diff for the next file
      ['<s-tab>'] = actions.select_prev_entry, -- Open the diff for the previous file
      ['gf'] = actions.goto_file, -- Open the file in a new split in the previous tabpage
      ['<C-w><C-f>'] = actions.goto_file_split, -- Open the file in a new split
      ['<C-w>gf'] = actions.goto_file_tab, -- Open the file in a new tabpage
      ['<leader>e'] = actions.focus_files, -- Bring focus to the files panel
      ['<leader>b'] = actions.toggle_files, -- Toggle the files panel.
    },
    file_panel = {
      ['j'] = actions.next_entry, -- Bring the cursor to the next file entry
      ['<down>'] = actions.next_entry,
      ['k'] = actions.prev_entry, -- Bring the cursor to the previous file entry.
      ['<up>'] = actions.prev_entry,
      ['<cr>'] = actions.select_entry, -- Open the diff for the selected entry.
      ['o'] = actions.select_entry,
      ['<2-LeftMouse>'] = actions.select_entry,
      ['-'] = actions.toggle_stage_entry, -- Stage / unstage the selected entry.
      ['S'] = actions.stage_all, -- Stage all entries.
      ['U'] = actions.unstage_all, -- Unstage all entries.
      ['X'] = actions.restore_entry, -- Restore entry to the state on the left side.
      ['R'] = actions.refresh_files, -- Update stats and entries in the file list.
      ['L'] = actions.open_commit_log, -- Open the commit log panel.
      ['<c-b>'] = actions.scroll_view(-0.25), -- Scroll the view up
      ['<c-f>'] = actions.scroll_view(0.25), -- Scroll the view down
      ['<tab>'] = actions.select_next_entry,
      ['<s-tab>'] = actions.select_prev_entry,
      ['gf'] = actions.goto_file,
      ['<C-w><C-f>'] = actions.goto_file_split,
      ['<C-w>gf'] = actions.goto_file_tab,
      ['i'] = actions.listing_style, -- Toggle between 'list' and 'tree' views
      ['f'] = actions.toggle_flatten_dirs, -- Flatten empty subdirectories in tree listing style.
      ['<leader>e'] = actions.focus_files,
      ['<leader>b'] = actions.toggle_files,
    },
    file_history_panel = {
      ['g!'] = actions.options, -- Open the option panel
      ['<C-A-d>'] = actions.open_in_diffview, -- Open the entry under the cursor in a diffview
      ['y'] = actions.copy_hash, -- Copy the commit hash of the entry under the cursor
      ['L'] = actions.open_commit_log,
      ['zR'] = actions.open_all_folds,
      ['zM'] = actions.close_all_folds,
      ['j'] = actions.next_entry,
      ['<down>'] = actions.next_entry,
      ['k'] = actions.prev_entry,
      ['<up>'] = actions.prev_entry,
      ['<cr>'] = actions.select_entry,
      ['o'] = actions.select_entry,
      ['<2-LeftMouse>'] = actions.select_entry,
      ['<c-b>'] = actions.scroll_view(-0.25),
      ['<c-f>'] = actions.scroll_view(0.25),
      ['<tab>'] = actions.select_next_entry,
      ['<s-tab>'] = actions.select_prev_entry,
      ['gf'] = actions.goto_file,
      ['<C-w><C-f>'] = actions.goto_file_split,
      ['<C-w>gf'] = actions.goto_file_tab,
      ['<leader>e'] = actions.focus_files,
      ['<leader>b'] = actions.toggle_files,
    },
    option_panel = {
      ['<tab>'] = actions.select_entry,
      ['q'] = actions.close,
    },
  }
end

-- lsp 回调函数快捷键设置
pluginKeys.mapLSP = function(mapbuf)
  -- rename
  --[[
  Lspsaga 替换 rn
  mapbuf("n", "<leader>rn", "<cmd>Lspsaga rename<CR>", opt)
  --]]
  mapbuf('n', '<leader>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opt)
  -- code action
  --[[
  Lspsaga 替换 ca
  mapbuf("n", "<leader>ca", "<cmd>Lspsaga code_action<CR>", opt)
  --]]
  mapbuf('n', '<leader>ca', '<cmd>lua vim.lsp.buf.code_action()<CR>', opt)
  -- go xx
  --[[
    mapbuf('n', 'gd', '<cmd>Lspsaga preview_definition<CR>', opt)
  mapbuf("n", "gd", "<cmd>lua vim.lsp.buf.definition()<CR>", opt)
  --]]
  mapbuf(
    'n',
    'gd',
    "<cmd>lua require'telescope.builtin'.lsp_definitions({ initial_mode = 'normal', })<CR>",
    opt
  )
  --[[
  mapbuf("n", "gh", "<cmd>Lspsaga hover_doc<cr>", opt)
  Lspsaga 替换 gh
  --]]
  mapbuf('n', 'gh', '<cmd>lua vim.lsp.buf.hover()<CR>', opt)
  --[[
  Lspsaga 替换 gr
  mapbuf("n", "gr", "<cmd>lua vim.lsp.buf.references()<CR>", opt)
  --]]
  mapbuf('n', 'gr', '<cmd>Lspsaga lsp_finder<CR>', opt)
  --[[
  Lspsaga 替换 gp, gj, gk
  mapbuf("n", "gp", "<cmd>lua vim.diagnostic.open_float()<CR>", opt)
  mapbuf("n", "gj", "<cmd>lua vim.diagnostic.goto_next()<CR>", opt)
  mapbuf("n", "gk", "<cmd>lua vim.diagnostic.goto_prev()<CR>", opt)
  --]]
  -- diagnostic
  mapbuf('n', 'gp', '<cmd>Lspsaga show_line_diagnostics<CR>', opt)
  mapbuf('n', 'gj', '<cmd>Lspsaga diagnostic_jump_next<cr>', opt)
  mapbuf('n', 'gk', '<cmd>Lspsaga diagnostic_jump_prev<cr>', opt)
  mapbuf('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opt)
  -- mapbuf("n", "<leader>f", "<cmd>lua vim.lsp.buf.format({ timeout_ms = 2000 })<CR>", opt)
  -- 未用
  -- mapbuf("n", "gD", "<cmd>lua vim.lsp.buf.declaration()<CR>", opt)
  -- mapbuf('n', '<leader>q', '<cmd>lua vim.diagnostic.setloclist()<CR>', opt)
  -- mapbuf("n", "<C-k>", "<cmd>lua vim.lsp.buf.signature_help()<CR>", opt)
  -- mapbuf('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opt)
  -- mapbuf('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opt)
  -- mapbuf('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opt)
  -- mapbuf('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opt)
end

-- nvim-cmp 自动补全
pluginKeys.cmp = function(cmp)
  local feedkey = function(key, mode)
    vim.api.nvim_feedkeys(
      vim.api.nvim_replace_termcodes(key, true, true, true),
      mode,
      true
    )
  end
  local has_words_before = function()
    local line, col = unpack(vim.api.nvim_win_get_cursor(0))
    return col ~= 0
      and vim.api
          .nvim_buf_get_lines(0, line - 1, line, true)[1]
          :sub(col, col)
          :match('%s')
        == nil
  end

  return {
    -- 上一个
    ['<C-p>'] = cmp.mapping.select_prev_item(),
    -- 下一个
    ['<C-n>'] = cmp.mapping.select_next_item(),
    -- 出现补全
    ['<A-.>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }),
    -- 取消
    ['<A-,>'] = cmp.mapping({
      i = cmp.mapping.abort(),
      c = cmp.mapping.close(),
    }),
    -- 确认
    -- Accept currently selected item. If none selected, `select` first item.
    -- Set `select` to `false` to only confirm explicitly selected items.
    ['<CR>'] = cmp.mapping.confirm({
      select = true,
      behavior = cmp.ConfirmBehavior.Replace,
    }),
    -- ['<C-y>'] = cmp.config.disable, -- Specify `cmp.config.disable` if you want to remove the default `<C-y>` mapping.
    -- 如果窗口内容太多，可以滚动
    ['<C-u>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
    ['<C-d>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),
    -- snippets 跳转
    ['<C-l>'] = cmp.mapping(function(_)
      if vim.fn['vsnip#available'](1) == 1 then
        feedkey('<Plug>(vsnip-expand-or-jump)', '')
      end
    end, { 'i', 's' }),
    ['<C-h>'] = cmp.mapping(function()
      if vim.fn['vsnip#jumpable'](-1) == 1 then
        feedkey('<Plug>(vsnip-jump-prev)', '')
      end
    end, { 'i', 's' }),

    -- super Tab
    ['<Tab>'] = cmp.mapping(function(fallback)
      if cmp.visible() then
        cmp.select_next_item()
      elseif vim.fn['vsnip#available'](1) == 1 then
        feedkey('<Plug>(vsnip-expand-or-jump)', '')
      elseif has_words_before() then
        cmp.complete()
      else
        fallback() -- The fallback function sends a already mapped key. In this case, it's probably `<Tab>`.
      end
    end, { 'i', 's' }),

    ['<S-Tab>'] = cmp.mapping(function()
      if cmp.visible() then
        cmp.select_prev_item()
      elseif vim.fn['vsnip#jumpable'](-1) == 1 then
        feedkey('<Plug>(vsnip-jump-prev)', '')
      end
    end, { 'i', 's' }),
    -- end of super Tab
  }
end

-- debug 被废弃
pluginKeys.mapVimspector = function()
  -- 开始
  map('n', '<leader>dd', ':call vimspector#Launch()<CR>', opt)
  -- 结束
  map('n', '<Leader>de', ':call vimspector#Reset()<CR>', opt)
  -- 继续
  map('n', '<Leader>dc', ':call vimspector#Continue()<CR>', opt)
  -- 设置断点
  map('n', '<Leader>dt', ':call vimspector#ToggleBreakpoint()<CR>', opt)
  map('n', '<Leader>dT', ':call vimspector#ClearBreakpoints()<CR>', opt)
  --  stepOver, stepOut, stepInto
  map('n', '<leader>dj', '<Plug>VimspectorStepOver', opt)
  map('n', '<leader>dk', '<Plug>VimspectorStepOut', opt)
  map('n', '<leader>dl', '<Plug>VimspectorStepInto', opt)
end

return pluginKeys
